using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using Toast.Compression;
using Toast.Core;
using Toast.Core.Interfaces;
using Toast.Extensions;

namespace Toast.ContentTypes
{
    [Serializable]
    public sealed class RemoteJavaScriptFile : JavaScriptContentBase
    {
        public RemoteJavaScriptFile()
        {
        }

        RemoteJavaScriptFile(string orginalPath, InjectAt injectAt)
        {
            OriginalPath = orginalPath;
            FileName = Path.GetFileName(orginalPath);
            InjectAt = injectAt;
        }

        public string OriginalPath { get; set; }
        public string Content { get; set; }

        public override IInjectionFormatter GetFormatter(string packageKey)
        {
            return new RemoteFileInjectionFormatter(packageKey);
        }


        public override bool TryConstructFrom(string from, out IContent result)
        {          
            if (!Regex.IsMatch(from, @"http?://([-\w\.]+)+(:\d+)?(/([\w/_\.]*(\?\S+)?)?)?\.js"))
            {
                result = null;
                return false;
            }
            
            result = new RemoteJavaScriptFile (from, InjectAt.Default);

            return true;                       
        }

        public static RemoteJavaScriptFile FromUrl(string path)
        {
            return FromUrl(path, InjectAt.Default);
        }

        public static RemoteJavaScriptFile FromUrl(string path, InjectAt injectAt)
        {
            return FromUrl(new Uri(path), injectAt);
        }

        public static RemoteJavaScriptFile FromUrl(Uri path)
        {
            return FromUrl(path, InjectAt.Default);
        }

        public static RemoteJavaScriptFile FromUrl(Uri path, InjectAt injectAt)
        {
            if (path.Scheme.ToLower() != "http") throw new ArgumentException("Supplied path is invalid, only http is accepted.", "path");
            return new RemoteJavaScriptFile(path.OriginalString, injectAt);
        }
    }

    public class RemoteFileInjectionFormatter : InjectionFormatter
    {
        readonly string _packageKey;

        public RemoteFileInjectionFormatter(string packageKey, string injectionFormat)
            : base(injectionFormat)
        {
            _packageKey = packageKey;
        }

        public RemoteFileInjectionFormatter(string packageKey)
            : base("<script type='text/javascript' src='{0}'></script>")
        {
            _packageKey = packageKey;
        }

        public override string Format(IContent javaScriptContent, bool seperate)
        {
            var typedScript = javaScriptContent as RemoteJavaScriptFile;

            if (typedScript == null)
                return null;

            return seperate
                       ? InjectionFormatString.FormatWith(typedScript.OriginalPath)
                       : typedScript.OriginalPath;
        }

        public override string Format(IEnumerable<IContent> scripts, bool seperate)
        {
            return scripts == null ? null : scripts.Select(x => Format(x, true)).Join("\r\n");
        }
    }
}